/*
 * Process.m
 */
#import "Process.h"

@implementation Process

-initFromCommand:(char **)argv
{
	[super init];
	
	if(argv==0 || argv[0]==0 || access(argv[0],X_OK)){
		return nil;
	}
	
	if(pipe(toProcess)== -1){
		[self free];
		return nil; /* could not open first pipe */
	}
	
	if(pipe(fromProcess)== -1){
		close(toProcess[0]);
		close(toProcess[1]);
		[self free];
		return nil;
	}
	
	pid=fork();
	
	if(pid== -1){
		[self free]; /* no more processes */
		return nil;
	}
	
	if(pid==0){
		/* executued by the child, set up and execv */
		close(0); 				/* stdin */
		close(1); 				/* stdout */

		close(toProcess[1]);
		close(fromProcess[0]);

		dup2(toProcess[0], 0); 	/* stdin */
		dup2(toProcess[1], 1); 	/* stdout */

		close(2); 				/* stderr */
		dup2(fromProcess[1], 2);/* stderr */

	execv(argv[0], argv);
	perror(NXArgv[0]);
	exit(1);
	}
	
	close(toProcess[0]);		/* exectude by parent */
	close(fromProcess[1]);		/* close the other ends of the pipe */
	return self;
}

- free
{
	if(fdHandlerInstalled) DPSRemoveFD(fromProcess[0]);
	if(toProcess[1]) close(toProcess[1]);
	if(fromProcess[0]) close(fromProcess[0]);
	if(pid>0) kill(pid,9);
	return [super free];
}

- (int)toFd
{
	return toProcess[1];
}

- (int)fromFd
{
	return fromProcess[0];
}

/* send a line to the process */
- writeLine:(const char *)aLine
{
	int len = strlen(aLine);
	
	write(toProcess[1], aLine, len);
	
	if(len>0 && aLine[len-1] != '\n'){
		write(toProcess[1], "\n", 1); /* courtesy */
	}
	
	return self;
}

- dpsWatchFD:(DPSFDProc)handler data:(void *)userData priority:(int)pri
{
	DPSAddFD(fromProcess[0], handler, userData, pri);
	fdHandlerInstalled = YES;
	return self;
}

@end


		
